/**
 * 树表组件
 * @author
 * @version 1.4.2
 * @lastUpdateDate 2011-09-03
 * @mail
 */
(function ($) {

    $.fn.treeTable = function (opts) {
        opts = $.extend({
            path: '', /**样式文件夹路径*/
            url: '', /**请求地址*/
            data: function () {
                return {}
            },
            datatype: 'json', /**返回数据格式*/
            mtype: 'GET', /**请求路径*/
            idField: 'id', /**主键属性名称*/
            theme: 'default', /**默认样式*/
            expandLevel: 1,
            column: 0,
            columns: [], /**列定义*/
            onSelect: function ($treeTable, id) {
            },
            beforeExpand: function ($treeTable, id) {
                renderChildren($treeTable, id);
            }
        }, opts);
        var $treeTable = this;
        $treeTable.addClass('tree_table');
        var css = {
            'N': opts.theme + '_node',
            'AN': opts.theme + '_active_node',
            'O': opts.theme + '_open',
            'LO': opts.theme + '_last_open',
            'S': opts.theme + '_shut',
            'LS': opts.theme + '_last_shut',
            'HO': opts.theme + '_hover_open',
            'HS': opts.theme + '_hover_shut',
            'HLO': opts.theme + '_hover_last_open',
            'HLS': opts.theme + '_hover_last_shut',
            'L': opts.theme + '_leaf',
            'LL': opts.theme + '_last_leaf',
            'B': opts.theme + '_blank',
            'V': opts.theme + '_vertline'
        };
        var pMap = {}, cMap = {};
        var queryParams = opts.data||{};
        //根据地址请求数据构建table结构
        init('load');

        function template() {
            if(arguments.length<2) return '';
            var s=arguments[0];
            for(var i=1; i<arguments.length; i++) {
                s = s.replace(new RegExp("\\{" + (i-1) + "\\}", "g"), arguments[i]);
            }
            return s;
        }
        function buildTR(opts, data, isTop) {
            //构建表内容
            var rowData;
            var htmBody = "";
            for (var i = 0; i < data.rows.length; i++) {
                rowData = data.rows[i];
                var pId = isTop ? '' : 'pId=' + rowData.parentId;
                var hasChild = ("true" == rowData.isLeaf) ? 'hasChild=true' : '';
                htmBody += "<tr " + hasChild + "  " + pId + " id='" + rowData[opts.idField] + "'><td hidden='true'>" + rowData[opts.idField] + "</td>";
                var fn,al,wh;
                for (var j = 0; j < opts.columns.length; j++) {
                     fn = opts.columns[j].formatter;
                     al=opts.columns[j].align;
                     wh=opts.columns[j].width;
                     al=al?template(" align='{0}'",al):'' ;
                     wh=wh?template(" width='{0}'",wh):'';
                     htmBody += template("<td {0} {1} >{2}</td>",al,wh, (typeof fn == 'function'?fn.call($treeTable, rowData, rowData[opts.columns[j].field]):rowData[opts.columns[j].field]));
                }
                htmBody += "</tr>";
            }
            return htmBody;
        }

        $treeTable.on("click", function (event) {
            var $target = $(event.target);

            if ($target.attr('controller')) {
                $target = $target.parents('tr[haschild]').find('[arrow]');
                //判断是否是叶子节点
                if ($target.attr('class').indexOf(css['AN']) == -1 && $target.attr('class').indexOf(css['N']) == -1) {
                    return;
                }
                var id = $target.parents('tr[haschild]')[0].id;
                if (opts.onSelect && opts.onSelect($treeTable, id) === false) {
                    return;
                }
            }

            if ($target.attr('arrow')) {
                var className = $target.attr('class');
                if (className == css['AN'] + ' ' + css['HLO'] || className == css['AN'] + ' ' + css['HO']) {
                    var id = $target.parents('tr[haschild]')[0].id;
                    $target.attr('class', css['AN'] + " " + (className.indexOf(css['HO']) != -1 ? css['HS'] : css['HLS']));

                    //关闭所有孩子的tr
                    shut(id);
                    return;
                } else if (className == css['AN'] + ' ' + css['HLS'] || className == css['AN'] + ' ' + css['HS']) {
                    var id = $target.parents('tr')[0].id;
                    $target.attr('class', css['AN'] + " " + (className.indexOf(css['HS']) != -1 ? css['HO'] : css['HLO']));

                    opts.beforeExpand($treeTable, id);
                    //展开所有直属节点，根据图标展开子孙节点
                    open(id);
                    return;
                }
            }
        });

        $treeTable.on("mouseover", hoverActiveNode).mouseout(hoverActiveNode);

        function hoverActiveNode(event) {
            var $target = $(event.target);

            if ($target.attr('controller')) {
                $target = $target.parents('tr[haschild]').find('[arrow]');
            }

            if ($target.attr('arrow')) {
                var className = $target.attr('class');
                if (className && !className.indexOf(css['AN'])) {
                    var len = opts.theme.length + 1;
                    className = className.split(' ')[1].substr(len);
                    if (className.indexOf('hover_') === 0) {
                        className = opts.theme + '_' + className.substr(6);
                    } else {
                        className = opts.theme + '_hover_' + className;
                    }

                    $target.attr('class', css['AN'] + ' ' + className);
                    return;
                }
            }
        }

        /** 初始化节点关系　*/
        function initRelation($trs, hideLevel) {
            //构造父子关系
            $trs.each(function (i) {
                var pId = $(this).attr('pId') || 0;
                pMap[pId] || (pMap[pId] = []);
                pMap[pId].push(this.id);
                cMap[this.id] = pId;

                //给这个tr增加类为了提高选择器的效率
                $(this).addClass(pId);
            }).find('[controller]').css('cursor', 'pointer');

            //标识父节点是否有孩子、是否最后一个节点
            $trs.each(function (i) {
                if (!this.id) {
                    return;
                }
                var $tr = $(this);

                pMap[this.id] && $tr.attr('hasChild', true);
                var pArr = pMap[cMap[this.id]];//当前节点的父节点下的所有子节点
                if (pArr[0] == this.id) {
                    $tr.attr('isFirstOne', true);
                } else {
                    var prevId = 0;
                    for (var i = 0; i < pArr.length; i++) {
                        if (pArr[i] == this.id) {
                            break;
                        }
                        prevId = pArr[i];
                    }
                    $tr.attr('prevId', prevId);
                }

                pArr[pArr.length - 1] == this.id && $tr.attr('isLastOne', true);

                var depth = getDepth(this.id);
                $tr.attr('depth', depth);

                //格式化节点
                formatNode(this);

                //判断是否要隐藏限制的层次
                if (hideLevel) {
                    depth > opts.expandLevel && $tr.hide();
                    //判断是否小于深度，如果小于深度则要换成展开的图标
                    if ($tr.attr('hasChild') && $tr.attr('depth') < opts.expandLevel) {
                        var className = $tr.attr('isLastOne') ? css['LO'] : css['O'];
                        $tr.find('.' + css['AN']).attr('class', css['AN'] + ' ' + className);
                    }
                }
            });

            //递归获取深度
            function getDepth(id) {
                if (cMap[id] == 0) {
                    return 1;
                }
                var $parentDepth = getDepth(cMap[id]);
                return $parentDepth + 1;
            }
        }

        //递归关闭所有的孩子
        function shut(id) {
            if (!pMap[id]) {
                return false;
            }
            for (var i = 0; i < pMap[id].length; i++) {
                shut(pMap[id][i]);
            }
            $('tr.' + id, $treeTable).hide();
        }

        //根据历史记录来展开节点
        function open(id) {
            $('tr.' + id, $treeTable).show();
            if (!pMap[id]) {
                return false;
            }
            for (var i = 0; i < pMap[id].length; i++) {
                var cId = pMap[id][i];
                if (pMap[cId]) {
                    var className = $('#' + cId, $treeTable).find('.' + css['AN']).attr('class');
                    //如果子节点是展开图表的，则需要展开此节点
                    (className == css['AN'] + ' ' + css['O'] || className == css['AN'] + ' ' + css['LO']) && open(cId);
                }
            }
        }

        function formatNode(tr) {
            var $cur = $(tr);
            var id = tr.id;

            //-------------下面一大段都是获取$preSpan---------
            if (cMap[id] == 0) {
                //如果是顶级节点，则没有prev_sp
                var $preSpan = $('<span class="prev_sp"></span>');
            } else {
                //先判断是否有上一个兄弟节点
                if (!$cur.attr('isFirstOne')) {
                    var $preSpan = $('#' + $cur.attr('prevId'), $treeTable).children("td").eq(opts.column).find('.prev_sp').clone();
                } else {
                    var $parent = $('#' + cMap[id], $treeTable);
                    //没有上一个兄弟节点，则使用父节点的prev_sp
                    var $preSpan = $parent.children("td").eq(opts.column).find('.prev_sp').clone();

                    //如果父亲后面没有兄弟，则直接加空白，若有则加竖线
                    if ($parent.attr('isLastOne')) {
                        $preSpan.append('<span class="' + css['N'] + ' ' + css['B'] + '"></span>');
                    } else {
                        $preSpan.append('<span class="' + css['N'] + ' ' + css['V'] + '"></span>');
                    }
                }
            }
            //------------------------------------------------

            if ($cur.attr('hasChild')) {
                //如果有下一个节点，并且下一个节点的父亲与当前节点的父亲相同，则说明该节点不是最后一个节点
                var className = $cur.attr('isLastOne') ? css['LS'] : css['S'];
                className = css['AN'] + ' ' + className;
            } else {
                var className = css['N'] + ' ' + ($cur.attr('isLastOne') ? css['LL'] : css['L']);
            }

            var $td = $cur.children("td").eq(opts.column);
            $td.prepend('<span arrow="true" class="' + className + '"></span>').prepend($preSpan);
        };

        function init(type) {
            queryParams = $treeTable.params;
            $.ajax({
                type: opts.mtype,
                url: opts.url,
                data: queryParams || {},
                dataType: opts.datatype,
                success: function (data) {
                    //构建表内容
                    var htmBody = "<tbody>";
                    htmBody += buildTR(opts, data, true);
                    htmBody += "</tbody>";
                    if ("load" == type) {
                        //构建表头
                        var htmHead = "<thead><tr>";
                        for (var hi = 0; hi < opts.columns.length; hi++) {
                            htmHead += "<th>" + opts.columns[hi].title + "</th>"
                        }
                        htmHead += "</tr></thead>";
                        //初始化表格内容
                        $treeTable.html("");
                        $treeTable.append(htmHead + htmBody);

                    }
                    if ("reload" == type) {
                        $treeTable.find("tbody").remove();
                        $treeTable.append(htmBody);
                    }
                    //初始化tree样式
                    initRelation($treeTable.find('tbody>tr'), true);

                }
            });
        }

        /***
         * 增加子项
         * @param $treeTable
         * @param id
         */
        function renderChildren($treeTable, id) {
            var url = opts.url + "?id=" + id;
            //判断id是否已经有了孩子节点，如果有了就不再加载，这样就可以起到缓存的作用
            if ($('.' + id, $treeTable).length) {
                return;
            }
            $.ajax({
                type: opts.mtype,
                url: url,
                data: queryParams || {},
                dataType: opts.datatype,
                success: function (data) {
                    $treeTable.addChilds(buildTR(opts, data, false));
                }
            });
        }

        $treeTable.addChilds = function (trsHtml) {
            var $trs = $(trsHtml);
            if (!$trs.length) {
                return false;
            }

            var pId = $($trs[0]).attr('pId');
            if (!pId) {
                return false;
            }
            //插入到最后一个孩子后面，或者直接插在父节点后面
            var insertId = pMap[pId] && pMap[pId][pMap[pId].length - 1] || pId;
            $('#' + insertId, $treeTable).after($trs);
            initRelation($trs);
        };
        /**查询参数*/
        $treeTable.params = function () {
            return queryParams;
        }
        $treeTable.reload = function () {
            pMap = {}, cMap = {};
            init('reload');
        }
        return $treeTable;
    };
})(jQuery);

